[EXP-23262]: S7: support subrepo cloning via GH_USER / GH_TOKEN#92
Conversation
pastey
left a comment
There was a problem hiding this comment.
I'm still not sure if we need GH_USER/GH_TOKEN in the s7 code. What are your thoughts?
| // GIT_CONFIG_COUNT) doesn't clobber it. | ||
| + (NSDictionary<NSString *, NSString *> *)gitHubTokenConfigEnvironmentForUser:(nullable NSString *)user | ||
| token:(nullable NSString *)token | ||
| existingConfigCount:(NSInteger)existingConfigCount |
There was a problem hiding this comment.
instead of passing existingConfigCount argument, I would directly access the
NSDictionary<NSString *, NSString *> *const env = NSProcessInfo.processInfo.environment;
const NSInteger existingConfigCount = MAX(0, [env[@"GIT_CONFIG_COUNT"] integerValue]);
here. This way all the logic managing GIT_CONFIG_COUNT would be in a single place. Now it's spread out by two methods.
Plus NSInteger seems odd. Why not unsigned?
There was a problem hiding this comment.
Valid point. Fixed with one small deviation: reading NSProcessInfo inside the builder would kill the tests, so instead the builder takes the environment as a parameter.
I've added those since they're used on Jenkins rn. And as far as I understand - Jenkins will use one PAT for all. So with current state of Jenkins we will have GH_* and S7_GIT_* values duplicated. S7_GIT_* are working in parallel and have higher priority. So in case if we will need to use separate token for S7 - we could. TBH I don't see the point in having duplicated values for two keys. But I do see actual case when we would like to have S7 specific credentials. In case if on system level we actually will retire GH_* env variable usage for all the project repos - then I'm fine to delete it :) |
pastey
left a comment
There was a problem hiding this comment.
Thank you for the changes. Looks almost perfect now 😍
Have few more suggestions 🙏
As for the GH_USER / S7_ – let it be. Duplicating the env variable in Jenkins configs will be too much of a pain indeed.
| } | ||
|
|
||
| NSMutableDictionary<NSString *, NSString *> *const result = [NSMutableDictionary new]; | ||
| __block NSUInteger nextConfigPairIndex = (NSUInteger)MAX(0, [processEnvironment[@"GIT_CONFIG_COUNT"] integerValue]); |
There was a problem hiding this comment.
nit:
| __block NSUInteger nextConfigPairIndex = (NSUInteger)MAX(0, [processEnvironment[@"GIT_CONFIG_COUNT"] integerValue]); | |
| __block NSUInteger nextConfigPairIndex = MAX(0, [processEnvironment[@"GIT_CONFIG_COUNT"] unsignedIntegerValue]); |
There was a problem hiding this comment.
processEnvironment[@"GIT_CONFIG_COUNT"] returns string, not NSNumber, so I won't be able to use unsignedIntegerValue here.
| if (configEnvironment.count > 0) { | ||
| NSMutableDictionary<NSString *, NSString *> *const merged = [env mutableCopy]; | ||
| [merged addEntriesFromDictionary:configEnvironment]; | ||
| taskEnvironment = [merged copy]; |
There was a problem hiding this comment.
I would suggest to put all the merging logic into the gitHubTokenConfigEnvironmentForUser itself.
Now the return value of the gitHubTokenConfigEnvironmentForUser is inconsistent: at one hand, it contains just the values we want to add, but the GIT_CONFIG_COUNT is the sum of our custom values and the keys from the original environment. If we try to use gitHubTokenConfigEnvironmentForUser as it's written now in some other place, we'd have to add the same merge there too.
There was a problem hiding this comment.
Plus, I would suggest to remove the call for copy.
- taskEnvironment = [merged copy];
+ taskEnvironment = merged;
I don't think we have some unscrupulous people casting NSDictionary to NSMutableDictionary around here.
| // keeps the original SSH URL, so the token never lands on disk either. | ||
| + (nullable NSDictionary<NSString *, NSString *> *)gitHubTokenAuthTaskEnvironment { | ||
| static dispatch_once_t onceToken; | ||
| static NSDictionary<NSString *, NSString *> *taskEnvironment; |
There was a problem hiding this comment.
I'm always scared by uninitialised variable. Even the static ones.
| static NSDictionary<NSString *, NSString *> *taskEnvironment; | |
| static NSDictionary<NSString *, NSString *> *taskEnvironment = nil; |
Ticket link
EXP-23262
Summary
Adds native support in s7 for authenticating GitHub subrepo network operations over HTTPS with a Personal Access Token, instead of relying on an SSH key.
When S7_GIT_USER + S7_GIT_TOKEN (or the GH_USER / GH_TOKEN fallback) are present, s7 makes git rewrite SSH github.com URLs to HTTPS and supplies the PAT as an HTTP Authorization header. When they're absent, behavior is unchanged — SSH as before.
How it works
All git invocations funnel through +[GitRepository runGitWithArguments:…]. When both credentials are present, s7 injects three GIT_CONFIG_* entries into the child git process's environment:
insteadOf moves the subrepo URL onto HTTPS transport; the github.com‑scoped extraheader authenticates it — the same approach actions/checkout uses. This is git ≥ 2.31's env-based config; no git config file is touched.
Security properties
Behavior details
Testing
Scope & follow-ups